/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package service

import (
	"sync"

	"hundsun.com/hsl/hschain/common/config"
	"hundsun.com/hsl/hschain/common/log/logging"
	"hundsun.com/hsl/hschain/executor/common"
	"hundsun.com/hsl/hschain/module"
	"hundsun.com/hsl/hschain/module/registry"
)

var once sync.Once
var log logging.Log

// GoroutineErrorWrapper goroutine错误包装
type GoroutineErrorWrapper struct {
	Error        error
	GoroutineTag string
}

type workerModule struct {
	module.Adapter
	shutdownWg     sync.WaitGroup
	workerInstance *WorkerService
}

// NewWorker 新建一个worker模块
func NewWorker() module.Module {
	m := &workerModule{}
	moduleStartupFunc := func(startedInterestedModules map[string][]*registry.ModRegKV) error {
		var err error
		once.Do(func() {
			log = m.Log
		})

		w := &WorkerService{}
		err = w.Init(m)
		if err != nil {
			return err
		}

		// 载入所有注册插件
		cntmp := config.GetPluginConfigsMapValue(common.ConfigKeyContract, nil)
		AddContracts(cntmp)

		m.workerInstance = w
		m.Log.Infof("module started:%s", w.config.ModuleID)

		// 定期向boss发布心跳
		m.shutdownWg.Add(1)
		go func() {
			defer m.shutdownWg.Done()
			w.pubHeartbeatToBoss()
		}()

		go w.procWorkMqMsg()

		return nil
	}

	m.Init(module.WorkerExecutorModuleName, m.GetInterestedModules(), moduleStartupFunc)
	return m
}

func (p *workerModule) Shutdown() (module.Status, error) {
	p.Log.Infof("shutdown %s", p.Config.ModuleID)
	p.RootCtxCancelFunc()
	p.shutdownWg.Wait()
	if p.workerInstance != nil {
		p.workerInstance.Close()
	}

	p.Status = module.StatusDown
	return p.Status, nil
}

func (p *workerModule) GetInterestedModules() []string {
	return []string{module.BlockchainModuleName}
}

func (p *workerModule) OnInterestedModuleUp(kv *registry.ModRegKV) (module.Status, error) {
	log.Printf("received a msg [Module Up] - from:'%s' to:'%s'", kv.Key, p.Config.ModuleID)
	log := p.Log.WithField(logging.LogFieldInterestedModule, kv.Value.ModuleName).
		WithField(logging.LogFieldInterestedModuleURL, kv.Value.ListenAddress.Format())
	log.Info("up")

	return p.Status, nil
}

func (p *workerModule) OnInterestedModuleDown(preKV *registry.ModRegKV) (module.Status, error) {
	log.Printf("received a msg [Module Down] - from:'%s' to:'%s'", preKV.Key, p.Config.ModuleID)
	log := p.Log.WithField(logging.LogFieldInterestedModule, preKV.Value.ModuleName).
		WithField(logging.LogFieldInterestedModuleURL, preKV.Value.ListenAddress.Format())
	log.Info("down")

	return p.Status, nil
}

func (p *workerModule) IsMasterStandbyMode() bool {
	return false
}

func (p *workerModule) IsMaster() bool {
	return false
}

func (p *workerModule) CompeteMaster() (bool, error) {
	return false, nil
}
